home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / music / cthugha5.zip / CTHU5SRC.ZIP / SB_DRIVE.C < prev    next >
C/C++ Source or Header  |  1994-08-19  |  36KB  |  1,678 lines

  1. /* Soundblaster Digital Audio driver for Borland C++.         *
  2.  *                                                            *
  3.  * Much of the program code is derived from various modules   *
  4.  * of the VangeliSTracker program, specifically SOUNDBLA.PAS  *
  5.  * and HARDWARE.PAS. Many thanks for making these wonderful   *
  6.  * sources available to the public. They basically allowed    *
  7.  * me to complete this project.                               *
  8.  *                                                                                  *
  9.  * Other portions of the code are derived from Michael        *
  10.  * Fulbright and Steve Haehnichen's SBMSDOS v1.0 code.        *
  11.  *                                                            *
  12.  * 31May94 zaph  : Slight changes to compile under MSC        *
  13.  *                                                            *
  14.  * Copyright (C) 1993 by Daniel Sachs                         *
  15.  * Parts Copyright (C) 1993 by VangeliSTeam                   *
  16.  * Parts Copyright (C) 1992 by Steve Haehnichen               */
  17.  
  18. #define SB_DRIVE
  19. // #define DEBUG_PROC
  20. // #define DEBUG_DMASTAT
  21.  
  22. #include "sb_drive.h"
  23. #include "dma.h"
  24. #include <dos.h>
  25. #include <stdlib.h>
  26. #ifdef _MSC_VER
  27. #include <memory.h>
  28. #include "patch.h"
  29. #define setvect(i,p) _dos_setvect(i,p)
  30. #define getvect(i) _dos_getvect(i)
  31. #define disable() _disable()
  32. #define enable() _enable()
  33. #else
  34. #include <mem.h>
  35. #endif
  36. #include <assert.h>
  37. #include <stdio.h>
  38. #include <string.h>
  39. #include <ctype.h>
  40. #include <conio.h>
  41.  
  42. #define AUTO_PREWRITE    // Uncomment to load entire buffer before
  43.                                 // starting playback. By default playback
  44.                                 // starts immediately.
  45.  
  46. int GUS = 0;                // Welp, the GUS needs some special treatment. :)
  47.  
  48. //#define WARN_OS2         // Uncomment to warn about 16-bit DMA incompatibilty
  49.  
  50. //#define DEBUG                // Uncomment for full debugging outputs.
  51.  
  52. //#define DEBUG_DMASTAT        // Uncomment for DMA buffer status information
  53. //#define DEBUG_PROC            // Uncomment for debug information from most functions.
  54. //#define DEBUG_WRITE         // Uncomment for debug information from dsp_write
  55. //#define DEBUG_FREE          // Uncomment for debug information from dsp_bufs_free
  56.  
  57. #ifdef DEBUG
  58. #define DEBUG_DMASTAT
  59. #define DEBUG_PROC
  60. #define DEBUG_WRITE
  61. #define DEBUG_FREE
  62. #endif
  63.  
  64. struct dsp_device_caps SB_caps[] =
  65. {
  66.     {    0,     0,     0,     0,     0,     0,     0,     0,     0, 0 }, // No SB
  67.     { 4000, 22222,     0,     0,     0, 11111,     0,     0,     0, 0 }, // SB 1.x
  68.     { 4000, 45454,     0,     0,     0, 15151,     0,     0,     0, 0 }, // SB 2.x
  69.     { 4000, 45454, 22727,     0,     0, 45454, 22727,     0,     0, 0 }, // SBPro
  70.     { 4000, 45454, 45454, 45454, 45454, 45454, 45454, 45454, 45454, 1 }  // SB16
  71. };
  72.  
  73. int SBport     = 0x220;
  74. int SBirq      = 5;
  75. int SBdma      = 1;
  76. int SBdma16    = 5;
  77.  
  78. int SBintnum;
  79. int SBtype;
  80.  
  81. int SBTimeOut    = 5000;        /* time to wait for DSP response */
  82.  
  83. int SBspeaker;                    // Speaker enabled?
  84.  
  85. unsigned char SBProMixRegs[] = { 0x22, 0x04, 0x26, 0x2E, 0x28, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00};
  86. unsigned char SB16MixRegs[]  = { 0x30, 0x32, 0x34, 0x38, 0x36, 0x41, 0x44, 0x46, 0x3F, 0x3A, 0x3B};
  87.  
  88. char SbOK;
  89.  
  90. int bufs_open;
  91.  
  92. char *DMABufferBase;
  93. char *DMABuffers[16];
  94.  
  95. unsigned DMABufferSize;
  96.  
  97. unsigned BufLen;
  98. unsigned BufCount;
  99.  
  100. unsigned BufTotal;
  101.  
  102. static char volatile BufQueueHead;
  103. static char volatile BufQueueTail;
  104.  
  105. static int volatile DMABufsFull;
  106. static int volatile DMAStopped = 1;
  107.  
  108. unsigned dsp_speed;
  109. char     dsp_bits;
  110. char        dsp_stereo;
  111. char       dsp_hispeed;
  112. char     dsp_signed;
  113.  
  114. int    volatile dsp_overrun;
  115.  
  116. #ifdef _MSC_VER
  117. void (_interrupt _far *old_irq_handler)();
  118. #else
  119. void interrupt (*old_irq_handler)(void);
  120. #endif
  121. void interrupt write_irq_handler(void);
  122. void interrupt null_irq_handler(void);
  123.  
  124. static void (*callback_function)(void);
  125.  
  126. char BitMasks[] = {0xFE, /* 1111 1110 */
  127.                          0xFD, /* 1111 1101 */
  128.                          0xFB, /* 1111 1011 */
  129.                          0xF7, /* 1111 0111 */
  130.                          0xEF, /* 1110 1111 */
  131.                          0xDF, /* 1101 1111 */
  132.                          0xBF, /* 1011 1111 */
  133.                          0x7F};/* 0111 1111 */
  134.  
  135. void SbWriteLoop(unsigned t)
  136. {
  137.     _asm {
  138.             MOV     BX,t
  139.             MOV    DX,[SBport]
  140.             ADD    DX,DSPWriteOffset
  141.     }
  142.  
  143. lp:    _asm {
  144.             DEC    BX
  145.             JZ        end
  146.             IN        AL,DX
  147.             ADD    AL,AL
  148.             JC        lp
  149.         }
  150. end:  _asm {
  151.             OR        BL,BH
  152.             MOV    [SbOK],BL
  153.     }
  154. }
  155.  
  156. void SbWriteByteTimeout(unsigned char command, unsigned timeout)
  157. {
  158.     SbWriteLoop(timeout);
  159.  
  160.     inp(DSPReadPort);
  161.  
  162.     SbWriteLoop(timeout);
  163.  
  164.     outp(DSPWritePort,command);
  165. }
  166.  
  167. void SbWriteByte(unsigned char command)
  168. {
  169.     SbWriteLoop(SBTimeOut);
  170.  
  171.     inp(DSPReadPort);
  172.  
  173.     SbWriteLoop(SBTimeOut);
  174.  
  175.     outp(DSPWritePort,command);
  176. }
  177.  
  178.  
  179. void SbReadLoop(unsigned t)
  180. {
  181.         _asm    MOV    BX,t
  182.         _asm     MOV    DX,[SBport]
  183.         _asm    ADD    DX,[DSPRStatOffset]
  184.  
  185. lp:    _asm    DEC    BX
  186.         _asm    JZ        fin
  187.         _asm    IN        AL,DX
  188.         _asm    ADD    AL,AL
  189.         _asm    JNC    lp
  190.  
  191. fin:    _asm    OR        BL,BH
  192.         _asm     MOV    [SbOK],BL
  193. }
  194.  
  195. unsigned char SbReadByte(unsigned timeout)
  196. {
  197.     SbReadLoop(timeout);
  198.     return inp(DSPReadPort);
  199. }
  200.  
  201. void SbWriteMixerReg(unsigned char reg, unsigned char value)
  202. {
  203.     outp(MixAddrPort,reg);
  204.     outp(MixDataPort,value);
  205. }
  206.  
  207. char SbReadMixerReg(unsigned char reg)
  208. {
  209.     outp(MixAddrPort,reg);
  210.     return inp(MixDataPort);
  211. }
  212.  
  213.  
  214. void EnableIRQ(char irq)
  215. {
  216.     disable();
  217.  
  218.     if( irq < 8 )
  219.         outp(0x21,inp(0x21) & BitMasks[irq]);
  220.     else
  221.     {
  222.         outp(0x21,inp(0x21) & BitMasks[1]);
  223.         outp(0xA1,inp(0xA1) & BitMasks[irq-8]);
  224.     }
  225.  
  226.     enable();
  227. }
  228.  
  229.  
  230. void DisableIRQ(char irq)
  231. {
  232.     disable();
  233.  
  234.     if( irq < 8 )
  235.         outp(0x21,inp(0x21) | (BitMasks[irq])^(0xFF));
  236.     else
  237.         outp(0xA1,inp(0xA1) | (BitMasks[irq-8])^(0xFF));
  238.  
  239.     enable();
  240. }
  241.  
  242.  
  243. int dsp_reset(void)
  244. {
  245.     int stat;
  246.     int ct;
  247.  
  248.     SBspeaker = 0;
  249.  
  250.     outp(DSPResetPort,1);
  251.     delay(50);
  252.     outp(DSPResetPort,0);
  253.  
  254.     for( ct=0; ct<100; ct++ )   // Reset DSP delay loop
  255.     {
  256.         inp(DSPRStatPort);
  257.         stat = inp(DSPReadPort);
  258.  
  259.         if( stat == 0xAA )
  260.             break;
  261.     }
  262.  
  263.     if( stat != 0xAA )
  264.         return 0;
  265.  
  266.     SBtype = (dsp_version() / 100);  // Return card type
  267.  
  268. #ifdef DEBUG_PROC
  269.     printf("dsp_reset: type %i\n",SBtype);
  270. #endif
  271.  
  272.     return SBtype;
  273.  
  274. }
  275.  
  276. int dsp_version(void)
  277. {
  278.     static int minor=0;
  279.     static int major=0;
  280.  
  281.     int i;
  282.                                                  
  283.     if( major == 0 )
  284.     {
  285.         SbWriteByte(DSPGetVersion);        /* Command to get DSP version */
  286.  
  287.         for( i=0; i<10; i++ )                // Wait for card to respond
  288.         {
  289.             major=SbReadByte(0xFFFF);
  290.  
  291.             if( (major != 0xAA) /* && (SbOK) */ )
  292.                 break;
  293.         }
  294.  
  295.         if( i==10 )
  296.             return 0;
  297.  
  298.         minor = SbReadByte(SBTimeOut);
  299.     }
  300.  
  301. #ifdef DEBUG_PROC
  302.     printf("dsp_version: %i.%02i\n",major,minor);
  303. #endif
  304.  
  305.     return ((major*100) + minor);            // Return numeric version number
  306. }
  307.  
  308.  
  309. void dsp_speaker(int status)
  310. {
  311. #ifdef DEBUG_PROC
  312.     printf("dsp_speaker: %s\n",status ? "on" : "off" );
  313. #endif
  314.  
  315.     if( SBtype >= 4 )
  316.         return;
  317.  
  318.     status = !!status;
  319.  
  320.     if( status != SBspeaker )
  321.         if( status )
  322.             SbWriteByte(DSPSpeakerOn);
  323.         else
  324.             SbWriteByte(DSPSpeakerOff);
  325.  
  326.     SBspeaker = status;
  327.  
  328.     delay(50);
  329. }
  330.  
  331. int dsp_open(int port, int dma, int irq, int dma16, unsigned bufsize, unsigned numbufs)
  332. {
  333.     char *work;
  334.  
  335.     long wlong;
  336.  
  337.     int  page;
  338.     unsigned offset;
  339.     unsigned segment;
  340.  
  341.     unsigned tot_bufsize;
  342.  
  343.     int i;
  344.  
  345.     work = getenv("ULTRASND");            // Check to see if we have a GUS
  346.  
  347.     if( work != NULL )
  348.     {
  349.         GUS = 1;
  350. #ifdef DEBUG_PROC
  351.         printf("dsp_open: Gravis Ultrasound detected.\n");
  352. #endif
  353.     }
  354.  
  355.     else
  356.         GUS = 0;
  357. #ifdef DEBUG_PROC
  358.     printf("dsp_open: port %x dma %i irq %i dma16 %i bufsize %i numbufs %i\n",port,dma,irq,dma16,bufsize,numbufs);
  359. #endif
  360.  
  361.     SBport  = port;                                // Set the configuration flags
  362.     SBdma      = dma;
  363.     SBirq   = irq;
  364.     SBdma16 = dma16;
  365.  
  366.     if(SBirq == 2)
  367.         SBirq = 9;
  368.  
  369.     SBintnum = SBirq + 8 + 96*(SBirq>7);
  370.  
  371.     if( (DMABufferBase != NULL) && ((numbufs != BufCount) || (bufsize != BufLen)) )
  372.         return 0;        // Sorry, once you set up buffers you're stuck with 'em.
  373.                             // All you can do is change the PORT/IRQ/DMA settings.
  374.  
  375.     if( (numbufs < 2) || (numbufs > 16) || (bufsize < 128) || (bufsize > 31774) )
  376.         return 0;        // Too many or too long buffers?
  377.  
  378.     if( bufsize % 4 )    // Buffer size has to be devisible by 4
  379.         bufsize = 4*((bufsize+4)/4);
  380.  
  381.     if( ((long)bufsize * numbufs) > 64000 )  // and can't be longer than 64K
  382.         return 0;
  383.  
  384.     tot_bufsize = bufsize * numbufs;            // How much we need to allocate
  385.  
  386.     if( !dsp_reset()  )                            // Reset the DSP. Is it there?
  387.         return 0;
  388.  
  389. #ifdef WARN_OS2
  390.     if( (SBtype == 4) && (dma16 >= 4) && (_osmajor >= 20) )
  391.     {
  392.         printf("Warning: 16-bit DMA does not work properly with OS/2.\n\n"
  393.                  "Press <Esc> to abort to DOS and select 8-bit DMA.\n"
  394.                  "Press <Enter> to ignore this warning and continue.\n");
  395.  
  396.         i = 0;
  397.  
  398.         while( (i != 27) && (i != 13) )
  399.             i = getch();
  400.  
  401.         if( i == 27 )
  402.             exit(100);
  403.     }
  404. #endif
  405.  
  406.     atexit(dsp_close);                            // Finish up when program exits
  407.  
  408.     BufLen   = bufsize;                            // Set up buffer configuration
  409.     BufCount = numbufs;
  410.  
  411.     BufTotal = tot_bufsize;
  412.  
  413.     if( DMABufferBase == NULL )                   // Make sure we haven't
  414.     {                                                             // done this already :)
  415.         work = calloc(1,tot_bufsize+1);
  416.  
  417.         if( work == NULL )
  418.             return 0;
  419.  
  420. // Allocate page-safe buffer:
  421.  
  422.         offset = ((FP_SEG(work)&0x0FFF)<<4) + FP_OFF(work);
  423.  
  424.         if( ((long)offset+tot_bufsize) > 65535L )  // Current buffer page-safe?
  425.         {
  426.             realloc(work,65536L-offset);                 // No: reallocate it
  427.  
  428.             DMABufferBase = calloc(1,tot_bufsize+1);// This should be :)
  429.             free(work);
  430.  
  431.             offset = ((FP_SEG(DMABufferBase)&0x0FFF)<<4) + FP_OFF(DMABufferBase);
  432.  
  433.             if( ((long)offset+tot_bufsize) > 65535L )
  434.             {
  435.                 printf("Unable to allocate page-safe buffer\n");
  436.                 exit(100);
  437.             }
  438.         }
  439.         else
  440.             DMABufferBase = work;                         // Current buffer OK
  441.  
  442.         if( DMABufferBase == NULL )
  443.             return 0;
  444.  
  445.         DMABufferSize = tot_bufsize;                     // Set up buffer pointers
  446.         for( i = 0; i < numbufs; i++ )
  447.             DMABuffers[i] = DMABufferBase + i*bufsize;
  448.     }
  449. #ifdef _MSC_VER
  450.     old_irq_handler = _dos_getvect(SBintnum);         // Save old interrupt
  451.     _dos_setvect(SBintnum,null_irq_handler);            // ...and stick ours in
  452. #else
  453.     old_irq_handler = getvect(SBintnum);         // Save old interrupt
  454.     setvect(SBintnum,null_irq_handler);            // ...and stick ours in
  455. #endif
  456.     callback_function = NULL;
  457.  
  458.     disable();
  459.  
  460.     BufQueueHead = 0;                                     // We're not playing anything
  461.     BufQueueTail = 0;
  462.     DMABufsFull = 0;
  463.     DMAStopped = 1;
  464.  
  465.     enable();
  466.  
  467.     EnableIRQ(SBirq);
  468.  
  469.     dsp_speaker(1);
  470.  
  471.     return SBtype;
  472. }
  473.  
  474. void dsp_close(void)
  475. {
  476. #ifdef DEBUG_PROC
  477.     printf("dsp_close\n");
  478. #endif
  479.  
  480.     dsp_pause_dma();
  481.     dma_reset(SBdma);
  482.     dma_reset(SBdma16);
  483.  
  484.     dsp_reset();
  485.  
  486.     if( SBtype <= 3 )
  487.         SbWriteByte(DSPSBProADCMono);
  488.  
  489.     DisableIRQ(SBirq);
  490. #ifdef _MSC_VER
  491.     _dos_setvect(SBintnum,old_irq_handler);            // Put things back to normal
  492. #else
  493.     setvect(SBintnum,old_irq_handler);            // Put things back to normal
  494. #endif
  495. }
  496.  
  497. void interrupt sbpro_bug_handler(void)            // To deal with the SBPro's channel swap bug.
  498. {
  499.     enable();
  500.  
  501.     inp(DSPIrqAck8Port);                                // Acknowledge interrupt
  502.  
  503.     dma_setup(SBdma,DMABufferBase,BufTotal-1,1);
  504.  
  505.     SbWriteByte(DSPSetHSDMASize);                    // Reset size (more than 1 byte :)
  506.     SbWriteByte((BufLen-1) % 256);
  507.     SbWriteByte((BufLen-1) / 256);
  508.  
  509.     SbWriteByte(DSPStartHSDMA);                    // Restart DMA with correct channels
  510.  
  511.     setvect(SBintnum,write_irq_handler);
  512.  
  513.     if( SBirq > 8 )
  514.         outp(0xA0,0x20);
  515.  
  516.     outp(0x20,0x20);                                    // Done with interrupt
  517. }
  518.  
  519.  
  520. void interrupt null_irq_handler(void)
  521. {
  522.     if( dsp_bits == 16 )
  523.         inp(DSPIrqAck16Port);                        // Acknowledge the SB's interupt
  524.     else
  525.         inp(DSPIrqAck8Port);
  526.  
  527.     if( SBirq > 8 )
  528.         outp(0xA0,0x20);
  529.  
  530.     outp(0x20,0x20);                                    // Done with interrupt
  531. }
  532.  
  533. void interrupt read_irq_handler(void)
  534. {
  535.     enable();
  536.  
  537.     if( dsp_bits == 16 )
  538.         inp(DSPIrqAck16Port);                        // Acknowledge the SB's interupt
  539.     else
  540.         inp(DSPIrqAck8Port);
  541.  
  542.     if( DMABufsFull == BufCount )  // Check for overrun
  543.     {
  544.         dsp_overrun++;                // We've got an overrun. Oops.
  545.  
  546.         BufQueueHead = BufQueueTail = (BufQueueTail+1) % BufCount;
  547.  
  548.         if( dsp_overrun > 16 )
  549.         {                       // We've got a LOT of overruns. Cancel
  550.             dsp_pause_dma();        // DMA. Someone forgot about it.
  551.             dma_reset(dsp_bits == 16 ? SBdma16 : SBdma);
  552.  
  553.             DMAStopped=1;
  554.  
  555.             BufQueueHead=0;
  556.             BufQueueTail=0;
  557.             DMABufsFull =0;
  558.  
  559.             setvect(SBintnum,null_irq_handler);
  560.  
  561.          SbWriteByte(DSPSBProADCMono);
  562.         }
  563.     }
  564.  
  565. #ifdef DEBUG_DMASTAT
  566.         {
  567.             poke(0xB800,154,11824+BufQueueHead);
  568.             poke(0xB800,156,11824+BufQueueTail);
  569.             poke(0xB800,158,11824+DMABufsFull);
  570.         }
  571. #endif
  572.  
  573.         BufQueueTail = (BufQueueTail+1) % BufCount;
  574.         DMABufsFull++;
  575.  
  576.         if( SBtype <= 3 )
  577.         {
  578.             if( dsp_hispeed )
  579.                 SbWriteByte(DSPStartHSADCDMA);
  580.             else
  581.             {
  582.                 SbWriteByte(DSPStartADCDMA);
  583.                 SbWriteByte((BufLen-1)%256);
  584.                 SbWriteByte((BufLen-1)/256);
  585.             }
  586.         }
  587.  
  588.         if( callback_function != NULL )
  589.             callback_function();
  590.  
  591.         if( SBirq > 8 )
  592.             outp(0xA0,0x20);
  593.         outp(0x20,0x20);
  594. }
  595.  
  596. void interrupt write_irq_handler(void)
  597. {
  598.     enable();
  599.  
  600.     if( DMABufsFull <= 1 )                            // Are we done playing everything?
  601.     {
  602.         if( dsp_bits == 16 )                            // Yup, ack the soundcard,
  603.             inp(DSPIrqAck16Port);
  604.         else
  605.             inp(DSPIrqAck8Port);
  606.  
  607.         SbWriteByte(DSPPauseDMA);                    // Kill playback
  608.  
  609.         setvect(SBintnum,null_irq_handler);        // Flip to other interrupt handler
  610.         dma_reset(dsp_bits == 16 ? SBdma16 : SBdma);  // Kill DMA
  611.  
  612.         DMAStopped = 1;                                // And flag it.
  613.         DMABufsFull = 0;
  614.  
  615.         BufQueueHead = 0;
  616.         BufQueueTail = 0;
  617.  
  618.         if( SBirq > 8 )
  619.             outp(0xA0,0x20);
  620.  
  621.         outp(0x20,0x20);                                // We're done.
  622.  
  623. #ifdef DEBUG_DMASTAT
  624.         {
  625.             poke(0xB800,154,20016+BufQueueHead);
  626.             poke(0xB800,156,20016+BufQueueTail);
  627.             poke(0xB800,158,20016+DMABufsFull);
  628.         }
  629.  
  630. #endif
  631.  
  632.         return;
  633.     }
  634.  
  635.     if( dsp_bits == 16 )                                // We're not done. 16 bits?
  636.     {
  637.         inp(DSPIrqAck16Port);                        // Yup. Acknowledge it to continue automatically.
  638.  
  639.         BufQueueHead = (BufQueueHead+1) % BufCount;  // Mark that buffer as played
  640.         DMABufsFull--;
  641.     }
  642.     else
  643.     {
  644.         inp(DSPIrqAck8Port);                            // No, 8 bits. So continue...
  645.  
  646.         BufQueueHead = (BufQueueHead+1) % BufCount;  // Mark that buffer as played
  647.         DMABufsFull--;
  648.  
  649.         if( GUS )
  650.             dma_setup(SBdma,DMABuffers[BufQueueHead],BufLen-1,1);
  651.  
  652.         if( SBtype < 4 )                           // Soundblaster 16 continues upon ack.
  653.             if( !dsp_hispeed )                  // Low-speed DMA mode
  654.             {
  655.                 SbWriteByte(DSPStartDMA);
  656.                 SbWriteByte((BufLen-1) % 256);
  657.                 SbWriteByte((BufLen-1) / 256);
  658.             }
  659.             else                                           // High-speed DMA mode
  660.                 SbWriteByte(DSPStartHSDMA);
  661.     }
  662.  
  663.     if( callback_function != NULL )               // Tell the caller that we've
  664.         callback_function();                                // gotten an interrupt.
  665.  
  666. #ifdef DEBUG_DMASTAT
  667.         {
  668.             poke(0xB800,154,11824+BufQueueHead);
  669.             poke(0xB800,156,11824+BufQueueTail);
  670.             poke(0xB800,158,11824+DMABufsFull);
  671.         }
  672. #endif
  673.  
  674.     if( SBirq > 8 )
  675.         outp(0xA0,0x20);
  676.  
  677.     outp(0x20,0x20);                                        // Complete the interrupt.
  678. }
  679.  
  680. void dsp_callback(void (*handler)(void))
  681. {
  682. #ifdef DEBUG_PROC
  683.     printf("dsp_callback: %p\n",handler);
  684. #endif
  685.  
  686.     callback_function = handler;
  687. }
  688.  
  689. int  dsp_buffers_free(void)
  690. {
  691.     int x;
  692.  
  693.     disable();
  694.     x = DMABufsFull;
  695.     enable();
  696.  
  697. #ifdef DEBUG_FREE
  698.     printf("dsp_buffers_free: %i\n",BufCount-x);
  699. #endif
  700.  
  701.     return BufCount - x;
  702. }
  703.  
  704. int dsp_active(void)
  705. {
  706.     return !DMAStopped;
  707. }
  708.  
  709. struct dsp_device_caps *dsp_get_device_caps(void)
  710. {
  711.     return &SB_caps[SBtype];
  712. }
  713.  
  714. unsigned dsp_set_record(unsigned speed, int stereo, int bits, int sign)
  715. {
  716.     dsp_speaker(0);
  717.  
  718.     if( SBtype >= 3 )
  719.         return dsp_set_sample(speed,stereo,bits,sign);
  720.  
  721.     if( SBtype == 2 )
  722.         if( speed <= 15151 )
  723.             return dsp_set_sample(speed,stereo,bits,sign);
  724.         else
  725.         {
  726. #ifdef DEBUG_PROC
  727.             printf("dsp_set_sample: speed %u %s%i %s\n",speed,stereo ? "stereo " : "", bits, sign ? "signed" : "unsigned");
  728.             printf("dsp_set_record: failure\n");
  729. #endif
  730.             return 0;
  731.         }
  732.  
  733.     if( SBtype == 1 )
  734.         if( speed <= 11111 )
  735.             return dsp_set_sample(speed,stereo,bits,sign);
  736.         else
  737.         {
  738. #ifdef DEBUG_PROC
  739.             printf("dsp_set_sample: speed %u %s%i %s\n",speed,stereo ? "stereo " : "", bits, sign ? "signed" : "unsigned");
  740.             printf("dsp_set_record: failure\n");
  741. #endif
  742.             return 0;
  743.         }
  744.  
  745.     return 0;
  746. }
  747.  
  748. unsigned dsp_set_sample(unsigned speed, int stereo, int bits, int sign)
  749. {
  750.     int x;
  751.     long test;
  752.  
  753.     stereo = !!stereo;
  754.     sign   = !!sign;
  755.  
  756. #ifdef DEBUG_PROC
  757.     printf("dsp_set_sample: speed %u %s%i %s\n",speed,stereo ? "stereo " : "", bits, sign ? "signed" : "unsigned");
  758. #endif
  759.  
  760.     dsp_pause_dma();
  761.  
  762.     if( !DMAStopped )                    // Was a playback going?
  763.         if( dsp_bits == 16 )            // Yes... 8 or 16 bit?
  764.             dma_reset(SBdma16);        // Reset 16 bit DMA
  765.         else
  766.             dma_reset(SBdma);            // Reset 8 bit DMA
  767.  
  768.     disable();
  769.     BufQueueHead = BufQueueTail = 0;        // Reset DMA variables
  770.     enable();
  771.  
  772.     dsp_speed = 0;
  773.  
  774.     if( sign && (SBtype < 4) )                    // Check for card's capabilities.
  775.         goto fail;
  776.  
  777.     dsp_signed = sign;
  778.  
  779.     if( speed < 4000 )
  780.         goto fail;
  781.  
  782.     if( stereo != 0 )
  783.         stereo = 1;
  784.  
  785.     if( stereo && (SBtype < 3) )
  786.         goto fail;
  787.  
  788.     if( (SBtype < 4) && (bits != 8) )
  789.         goto fail;
  790.  
  791.     if( (bits != 8) && (bits != 16 ) )
  792.         goto fail;
  793.  
  794.     if( (speed > 22222) & (SBtype == 1) )
  795.         goto fail;
  796.  
  797.     if( stereo && (SBtype == 3) )
  798.     {
  799.         test  = speed * 2L;
  800.  
  801.         speed *= 2;                                // SBPro requires 2x speed for stereo.
  802.     }
  803.     else
  804.         test = speed;
  805.  
  806.     if( test > 45454 )
  807.         goto fail;
  808.  
  809.     dsp_set_speed(&speed);                    // Set speed.
  810.  
  811.     if( SBtype == 3 )
  812.     {
  813.         x = SbReadMixerReg(0x0E);   // Set stereo control bit in mixer
  814.         SbWriteMixerReg(0x0E,x & 0xFD);
  815.  
  816.         SbWriteMixerReg(0x0E,(x & 0xFD) + 2*stereo);
  817.     }
  818.  
  819.     if( stereo && (SBtype == 3) )
  820.         speed /= 2;                                // Real speed.
  821.  
  822.     dsp_speed = speed;                        // Set variables for IRQ routines.
  823.     dsp_bits = bits;
  824.     dsp_stereo = stereo;
  825.  
  826.     disable();
  827.     DMAStopped = 1;                            // Reset DMA variables.
  828.     DMABufsFull = 0;
  829.     enable();
  830.  
  831. fail:
  832. #ifdef DEBUG_PROC
  833.     printf("dsp_set_playback: %s\n",speed > 0 ? "success" : "failure");
  834. #endif
  835.  
  836.     return dsp_speed;                            // Return true speed on success.
  837. }
  838.  
  839. void dsp_set_speed(unsigned *speed)
  840. {
  841.     static char time_const;
  842.  
  843.     unsigned speed0,speed1;
  844.  
  845.     if( *speed != 0 )
  846.     {
  847.         time_const = 0;
  848.  
  849.         if( SBtype >= 4 )
  850.         {
  851.             if( (*speed >= 44000) && (*speed < 44700) )
  852.             {
  853.                 *speed = 44100;
  854.                 time_const = 1;
  855.             }
  856.  
  857.             if( (*speed >= 22000) && (*speed < 22120) )
  858.             {
  859.                 *speed = 22050;
  860.                 time_const = 2;
  861.             }
  862.  
  863.             if( (*speed >= 11000) && (*speed < 11080) )
  864.             {
  865.                 *speed = 11025;
  866.                 time_const = 3;
  867.             }
  868.         }
  869.  
  870.         if( !time_const )
  871.         {
  872.             if( SBtype >= 2 )     // Can we use high-speed DMA?
  873.             {
  874.                 time_const = (char)((65536L-(256000000L / (long)*speed)) >> 8);
  875.  
  876.                 speed0 = (256000000L/(65536L-((long)(time_const  )<< 8)));
  877.                 speed1 = (256000000L/(65536L-((long)(time_const+1)<< 8)));
  878.  
  879.                 if( (*speed - speed0) > (speed1 - *speed) )
  880.                 {
  881.                     time_const++;
  882.                     *speed = speed1;
  883.                 }
  884.                 else
  885.                     *speed = speed0;
  886.  
  887.                 dsp_speed = *speed;
  888.                 dsp_hispeed = 1;
  889.             }
  890.             else
  891.             {
  892.                 time_const = (char)(256-(1000000 / *speed));
  893.  
  894.                 speed0 = 1000000 / (256-(time_const  ));
  895.                 speed1 = 1000000 / (256-(time_const+1));
  896.  
  897.                 if( (*speed - speed0) > (speed1 - *speed) )
  898.                 {
  899.                     time_const++;
  900.                     *speed = speed1;
  901.                 }
  902.                 else
  903.                     *speed = speed0;
  904.  
  905.                 dsp_speed = *speed;
  906.                 dsp_hispeed = 0;
  907.             }
  908.         }
  909.     }
  910.  
  911.     switch(time_const)
  912.     {
  913.  
  914.         case 1:
  915.             SbWriteByte(DSPSB16SetSpeed);
  916.             SbWriteByte(172);                    // 44100 / 256
  917.             SbWriteByte(68);                    // 44100 % 256
  918.         break;
  919.  
  920.         case 2:
  921.             SbWriteByte(DSPSB16SetSpeed);
  922.             SbWriteByte(86);                    // 22050 / 256
  923.             SbWriteByte(34);              // 22050 % 256
  924.         break;
  925.  
  926.         case 3:
  927.             SbWriteByte(DSPSB16SetSpeed);
  928.             SbWriteByte(43);                    // 11025 / 256
  929.             SbWriteByte(17);                    // 11025 % 256
  930.         break;
  931.  
  932.         default:
  933.             SbWriteByte(DSPSetTimeConstant);
  934.             SbWriteByteTimeout(time_const,SBTimeOut*5);
  935.         break;
  936.    }
  937.  
  938. #ifdef DEBUG_PROC
  939.     if( *speed )
  940.         printf("dsp_set_speed: true speed %u  time constant %i\n",*speed,(int)time_const);
  941.     else
  942.         printf("dsp_set_speed: resetting time constant %i\n",(int)time_const);
  943. #endif
  944. }
  945.  
  946. void dsp_pause_dma(void)
  947. {
  948.     SbWriteByte(DSPPauseDMA);                // Issue Pause DMA command.
  949.  
  950. #ifdef DEBUG_PROC
  951.     printf("dsp_pause_dma\n");
  952. #endif
  953. }
  954.  
  955. int dsp_continue_dma(void)
  956. {
  957.     int x;
  958.  
  959.     disable();
  960.     x = DMABufsFull;
  961.     enable();
  962.  
  963.     if( x==0 )
  964.         return 0;                                // We're not playing. Forget it.
  965.  
  966.     if( dsp_bits == 16 )
  967.         SbWriteByte(DSPContinueDMA);        // Kluge for 16-bits. [Shrug]
  968.  
  969.     SbWriteByte(DSPContinueDMA);            // Issue Continue DMA command.
  970.  
  971. #ifdef DEBUG_PROC
  972.     printf("dsp_continue_dma\n");
  973. #endif
  974.  
  975.     return 1;
  976. }
  977.  
  978. void *dsp_open_buf(void)
  979. {
  980.  
  981.     if( DMABufsFull == BufCount )                // Is the buffer full?
  982.     {
  983.         return NULL;
  984.     }
  985.     else
  986.     {
  987. #ifdef DEBUG_WRITE
  988.         printf("dsp_open_buf: success %p\n",DMABuffers[BufQueueTail]);
  989. #endif
  990.         bufs_open = 1;
  991.  
  992.         return DMABuffers[BufQueueTail];
  993.     }
  994. }
  995.  
  996. void dsp_close_buf(void)
  997. {
  998.  
  999.     int start;
  1000.     int tail;
  1001.  
  1002.     unsigned speed_dummy = 0;
  1003.  
  1004.     if( !bufs_open )
  1005.         if( DMABufsFull && DMAStopped )
  1006.         {
  1007.             setvect(SBintnum,write_irq_handler);                // Set up interrupts.
  1008.             DMAStopped = 0;
  1009.             goto start_playback;
  1010.         }
  1011.         else
  1012.             return;
  1013.  
  1014.     bufs_open = 0;
  1015.  
  1016.     disable();
  1017.  
  1018. #ifdef DEBUG_WRITE
  1019.     printf("dsp_close_buf\n");
  1020. #endif
  1021.  
  1022.     enable();                                        // No.
  1023.  
  1024.     disable();
  1025.     start = DMAStopped;                            // Find out if DMA is running currently
  1026.     enable();
  1027.  
  1028. #ifdef AUTO_PREWRITE
  1029.     if( (start) && (BufQueueTail < (BufCount-1)) )            // If prewrite is
  1030.     {
  1031.  
  1032.         disable();
  1033.         BufQueueHead = 0;                            // Tell dsp_write we've done it.
  1034.         BufQueueTail++;
  1035.         DMABufsFull++;
  1036.         enable();
  1037.  
  1038. #ifdef DEBUG_DMASTAT
  1039.         poke(0xB800,154,20016+BufQueueHead);
  1040.         poke(0xB800,156,20016+BufQueueTail);
  1041.         poke(0xB800,158,20016+DMABufsFull);
  1042. #endif
  1043.         return;
  1044.     }
  1045. #endif
  1046.  
  1047.     if( !start )
  1048.     {
  1049.         disable();
  1050.         BufQueueTail++;                                            // Move tail to account for it
  1051.  
  1052.         if( BufQueueTail >= BufCount )                        // Wrap tail
  1053.             BufQueueTail = 0;
  1054.  
  1055.         DMABufsFull++;                                                // Mark another buffer as full.
  1056.         enable();
  1057.     }
  1058.     else
  1059.     {
  1060.         if( SBtype < 4 )
  1061.             dsp_speaker(1);
  1062.  
  1063.         disable();                                      // Set up DMA variables.
  1064.         BufQueueHead = 0;
  1065.         BufQueueTail++;
  1066.         DMABufsFull++;
  1067.         DMAStopped = 0;
  1068.  
  1069.         if( BufQueueTail >= BufCount )                        // Wrap tail
  1070.             BufQueueTail = 0;
  1071.  
  1072.         enable();
  1073.  
  1074. start_playback:
  1075.         if( SBtype >= 4 )
  1076.         {
  1077.             setvect(SBintnum,write_irq_handler);            // Set up interrupts.
  1078.  
  1079.             dsp_reset();                                            // Reset DSP
  1080.             dsp_set_speed(&speed_dummy);                        // Set DMA speed.
  1081.  
  1082.             if( dsp_bits == 8 )
  1083.             {
  1084.                 dma_reset(SBdma);                                    // Setup 8-bit SB16 DMA
  1085.  
  1086.                 SbWriteByte(DSPSB16Start8DMA);
  1087.                 SbWriteByte((0x20*dsp_stereo)+(0x10*dsp_signed));
  1088.                 SbWriteByte((BufLen-1) % 256);
  1089.                 SbWriteByte((BufLen-1) / 256);
  1090.  
  1091.                 dma_setup(SBdma,DMABufferBase,BufTotal-1,1);
  1092.             }
  1093.             else
  1094.             {
  1095.                 dma_reset(SBdma16);                                // Setup 16-bit DMA
  1096.  
  1097.                 SbWriteByte(DSPSB16Start16DMA);
  1098.                 SbWriteByte((0x20*dsp_stereo)+(0x10*dsp_signed));
  1099.                 SbWriteByte(((BufLen-2)/2) % 256);
  1100.                 SbWriteByte(((BufLen-2)/2) / 256);
  1101.  
  1102.                 dma_setup(SBdma16,DMABufferBase,BufTotal-1,1);
  1103.             }
  1104.         }
  1105.         else
  1106.         {
  1107.             dma_reset(SBdma);
  1108.  
  1109.             if( dsp_stereo )
  1110.             {
  1111.                 setvect(SBintnum,sbpro_bug_handler);    // (grin)
  1112.  
  1113.                 dma_setup(SBdma,DMABufferBase+1,0,1);
  1114.  
  1115.                 SbWriteByte(DSPStartHSDMA);                // To avoid bug in SBPro playback,
  1116.                 SbWriteByte(0);                                // we have to play back a one-byte sample.
  1117.                 SbWriteByte(0);                                // How stupid.
  1118.             }
  1119.             else
  1120.             {
  1121.                 setvect(SBintnum,write_irq_handler);    // Set up interrupts.
  1122.  
  1123.                 if( GUS )
  1124.                     dma_setup(SBdma,DMABuffers[0],BufLen-1,1);
  1125.                 else
  1126.                     dma_setup(SBdma,DMABufferBase,BufTotal-1,1);
  1127.  
  1128.                 if( dsp_hispeed )
  1129.                 {
  1130.                     SbWriteByte(DSPSetHSDMASize);                    // High speed mode
  1131.                     SbWriteByte((BufLen-1) % 256);
  1132.                     SbWriteByte((BufLen-1) / 256);
  1133.  
  1134.                     SbWriteByte(DSPStartHSDMA);
  1135.                 }
  1136.                 else
  1137.                 {
  1138.                     SbWriteByte(DSPStartDMA);                      // Low speed mode
  1139.  
  1140.                     SbWriteByte((BufLen-1) % 256);
  1141.                     SbWriteByte((BufLen-1) / 256);
  1142.                 }
  1143.             }
  1144.         }
  1145.     }
  1146.  
  1147. #ifdef DEBUG_DMASTAT
  1148.     poke(0xB800,154,11824+BufQueueHead);
  1149.     poke(0xB800,156,11824+BufQueueTail);
  1150.     poke(0xB800,158,11823+DMABufsFull);
  1151. #endif
  1152.  
  1153.     return;
  1154. }
  1155. int dsp_prewrite(void *buffer)
  1156. {
  1157.     int start;
  1158.     int tail;
  1159.  
  1160. #ifdef DEBUG_WRITE
  1161.     printf("dsp_prewrite: %p\n",buffer);
  1162. #endif
  1163.  
  1164.     if( BufQueueTail == (BufCount-1) )        // Is there room?
  1165.         return 0;                                    // No.
  1166.  
  1167.     disable();
  1168.     start = DMAStopped;                            // Are we running already?
  1169.     enable();
  1170.  
  1171.     if( !start )
  1172.     {
  1173.         return 0;                                    // Yes.
  1174.     }
  1175.     else
  1176.     {
  1177.         memcpy(DMABuffers[BufQueueTail],buffer,BufLen);  // Copy prewrite into buffer
  1178.  
  1179.         disable();
  1180.         BufQueueHead = 0;                            // Tell dsp_write we've done it.
  1181.         BufQueueTail++;
  1182.         DMABufsFull++;
  1183.         enable();
  1184.  
  1185. #ifdef DEBUG_DMASTAT
  1186.         poke(0xB800,154,20016+BufQueueHead);
  1187.         poke(0xB800,156,20016+BufQueueTail);
  1188.         poke(0xB800,158,20016+DMABufsFull);
  1189. #endif
  1190.     }
  1191.  
  1192.     return 1;                                        // Success.
  1193. }
  1194.  
  1195. int dsp_write(void *buffer)
  1196. {
  1197.     int start;
  1198.     int tail;
  1199.  
  1200.     unsigned speed_dummy = 0;
  1201.  
  1202.     if( buffer == NULL )
  1203.         if( DMABufsFull && DMAStopped )
  1204.         {
  1205.             setvect(SBintnum,write_irq_handler);                // Set up interrupts.
  1206.             DMAStopped = 0;
  1207.             goto start_playback;
  1208.         }
  1209.         else
  1210.             return 0;
  1211.  
  1212.     disable();
  1213.     if( DMABufsFull == BufCount )                // Is the buffer full?
  1214.     {
  1215.         enable();                                    // Yes, can't write.
  1216.         return 0;
  1217.     }
  1218.  
  1219. #ifdef DEBUG_WRITE
  1220.     printf("dsp_write: %p\n",buffer);
  1221. #endif
  1222.  
  1223.     enable();                                        // No.
  1224.  
  1225.     disable();
  1226.     start = DMAStopped;                            // Find out if DMA is running currently
  1227.     enable();
  1228.  
  1229. #ifdef AUTO_PREWRITE
  1230.     if( (start) && (BufQueueTail < (BufCount-1)) )            // If prewrite is
  1231.     {
  1232.         dsp_prewrite(buffer);                                        // requested, do it.
  1233.         return 1;
  1234.     }
  1235. #endif
  1236.  
  1237.     if( !start )
  1238.     {
  1239.         memcpy(DMABuffers[BufQueueTail],buffer,BufLen); // Copy data into DMA buffer
  1240.  
  1241.         disable();
  1242.         BufQueueTail++;                                            // Move tail to account for it
  1243.  
  1244.         if( BufQueueTail >= BufCount )                        // Wrap tail
  1245.             BufQueueTail = 0;
  1246.  
  1247.         DMABufsFull++;                                                // Mark another buffer as full.
  1248.         enable();
  1249.     }
  1250.     else
  1251.     {
  1252.         if( SBtype < 4 )
  1253.             dsp_speaker(1);
  1254.  
  1255.         memcpy(DMABuffers[BufQueueTail],buffer,BufLen);    // Copy data into DMA buffer
  1256.  
  1257.         disable();                                      // Set up DMA variables.
  1258.         BufQueueHead = 0;
  1259.         BufQueueTail++;
  1260.         DMABufsFull++;
  1261.         DMAStopped = 0;
  1262.  
  1263.         if( BufQueueTail >= BufCount )                        // Wrap tail
  1264.             BufQueueTail = 0;
  1265.  
  1266.         enable();
  1267.  
  1268. start_playback:                                                   // Go here to start DMA, no questions
  1269.         if( SBtype >= 4 )
  1270.         {
  1271.             setvect(SBintnum,write_irq_handler);            // Set up interrupts.
  1272.  
  1273.             dsp_reset();                                            // Reset DSP
  1274.             dsp_set_speed(&speed_dummy);                        // Set DMA speed.
  1275.  
  1276.             if( dsp_bits == 8 )
  1277.             {
  1278.                 dma_reset(SBdma);                                    // Setup 8-bit SB16 DMA
  1279.  
  1280.                 SbWriteByte(DSPSB16Start8DMA);
  1281.                 SbWriteByte((0x20*dsp_stereo)+(0x10*dsp_signed));
  1282.                 SbWriteByte((BufLen-1) % 256);
  1283.                 SbWriteByte((BufLen-1) / 256);
  1284.  
  1285.                 dma_setup(SBdma,DMABufferBase,BufTotal-1,1);
  1286.             }
  1287.             else
  1288.             {
  1289.                 dma_reset(SBdma16);                                // Setup 16-bit DMA
  1290.  
  1291.                 SbWriteByte(DSPSB16Start16DMA);
  1292.                 SbWriteByte((0x20*dsp_stereo)+(0x10*dsp_signed));
  1293.                 SbWriteByte(((BufLen-2)/2) % 256);
  1294.                 SbWriteByte(((BufLen-2)/2) / 256);
  1295.  
  1296.                 dma_setup(SBdma16,DMABufferBase,BufTotal-1,1);
  1297.             }
  1298.         }
  1299.         else
  1300.         {
  1301.             dma_reset(SBdma);
  1302.  
  1303.             if( dsp_stereo )
  1304.             {
  1305.                 setvect(SBintnum,sbpro_bug_handler);    // (grin)
  1306.  
  1307.                 dma_setup(SBdma,DMABufferBase+1,0,1);
  1308.  
  1309.                 SbWriteByte(DSPSetHSDMASize);          // To avoid bug in SBPro playback,
  1310.                 SbWriteByte(0);                                // we have to play back a one-byte sample.
  1311.                 SbWriteByte(0);                                // How stupid.
  1312.  
  1313.                 SbWriteByte(DSPStartHSDMA);
  1314.             }
  1315.             else
  1316.             {
  1317.                 setvect(SBintnum,write_irq_handler);    // Set up interrupts.
  1318.  
  1319.                 if( GUS )
  1320.                     dma_setup(SBdma,DMABuffers[0],BufLen-1,1);
  1321.                 else
  1322.                     dma_setup(SBdma,DMABufferBase,BufTotal-1,1);
  1323.  
  1324.                 if( dsp_hispeed )
  1325.                 {
  1326.                     SbWriteByte(DSPSetHSDMASize);                    // High speed mode
  1327.                     SbWriteByte((BufLen-1) % 256);
  1328.                     SbWriteByte((BufLen-1) / 256);
  1329.  
  1330.                     SbWriteByte(DSPStartHSDMA);
  1331.                 }
  1332.                 else
  1333.                 {
  1334.                     SbWriteByte(DSPStartDMA);                      // Low speed mode
  1335.  
  1336.                     SbWriteByte((BufLen-1) % 256);
  1337.                     SbWriteByte((BufLen-1) / 256);
  1338.                 }
  1339.             }
  1340.         }
  1341.     }
  1342.  
  1343. #ifdef DEBUG_DMASTAT
  1344.     poke(0xB800,154,11824+BufQueueHead);
  1345.     poke(0xB800,156,11824+BufQueueTail);
  1346.     poke(0xB800,158,11823+DMABufsFull);
  1347. #endif
  1348.  
  1349.     return 1;
  1350. }
  1351.  
  1352. int dsp_read(void *ptr)
  1353. {
  1354.     unsigned speed_dummy = 0;
  1355.  
  1356. #ifdef DEBUG_WRITE
  1357.     printf("dsp_read: %p\n",ptr);
  1358. #endif
  1359.  
  1360.     if( ptr == NULL )
  1361.     {
  1362.         setvect(SBintnum,null_irq_handler);
  1363.  
  1364.         dma_reset(dsp_bits == 16 ? SBdma16 : SBdma);
  1365.  
  1366.         if( SBtype == 3 )
  1367.               SbWriteByte(DSPSBProADCMono);
  1368.  
  1369. #ifdef DEBUG_DMASTAT
  1370.         poke(0xB800,154,7*256+32);
  1371.         poke(0xB800,156,7*256+32);
  1372.         poke(0xB800,158,7*256+32);
  1373. #endif
  1374.  
  1375.         return 4;
  1376.     }
  1377.  
  1378.     if( DMAStopped )
  1379.     {
  1380.         dsp_speaker(0);
  1381.  
  1382.         if( SBtype == 3 )
  1383.             if( dsp_stereo )
  1384.             {
  1385.                 SbWriteByte(DSPSBProADCStereo);
  1386.                 SbWriteMixerReg(0x0E,(SbReadMixerReg(0x0E)&0xFD));
  1387.  
  1388.                 SbWriteMixerReg(0x0C,(SbReadMixerReg(0x0C)|(0x20)));
  1389.             }
  1390.             else
  1391.             {
  1392.                 SbWriteByte(DSPSBProADCMono);
  1393.                 SbWriteMixerReg(0x0E,SbReadMixerReg(0x0E)&0xFD);
  1394.  
  1395.                 if( dsp_speed <= 8000 )
  1396.                     SbWriteMixerReg(0x0C,SbReadMixerReg(0x0C)&(0xDF));
  1397.                 else
  1398.                     SbWriteMixerReg(0x0C,SbReadMixerReg(0x0C)|(0x20));
  1399.             }
  1400.  
  1401.         BufQueueHead = 0;
  1402.         BufQueueTail = 0;
  1403.         DMABufsFull  = 0;
  1404.         DMAStopped   = 0;
  1405.  
  1406.         dsp_overrun  = 0;
  1407.  
  1408.         setvect(SBintnum,read_irq_handler);
  1409.  
  1410.         if( SBtype >= 4 )
  1411.         {
  1412.             dsp_reset();
  1413.             dsp_set_speed(&speed_dummy);
  1414.  
  1415.             if( dsp_bits == 8 )
  1416.             {
  1417.                 SbWriteByte(DSPSB16Start8ADCDMA);
  1418.                 SbWriteByte((0x20*dsp_stereo)+(0x10*dsp_signed));
  1419.                 SbWriteByte((BufLen-1) % 256);
  1420.                 SbWriteByte((BufLen-1) / 256);
  1421.             }
  1422.             else
  1423.             {
  1424.                 SbWriteByte(DSPSB16Start16ADCDMA);
  1425.                 SbWriteByte((0x20*dsp_stereo)+(0x10*dsp_signed));
  1426.                 SbWriteByte(((BufLen-2)/2) % 256);
  1427.                 SbWriteByte(((BufLen-2)/2) / 256);
  1428.             }
  1429.             dma_setup(dsp_bits == 16 ? SBdma16 : SBdma,DMABufferBase,BufTotal-1,0);
  1430.         }
  1431.         else
  1432.         {
  1433.             if( dsp_hispeed )
  1434.             {
  1435.                 SbWriteByte(DSPSetHSDMASize);                    // High speed mode
  1436.                 SbWriteByte((BufLen-1) % 256);
  1437.                 SbWriteByte((BufLen-1) / 256);
  1438.  
  1439.                 SbWriteByte(DSPStartHSADCDMA);
  1440.             }
  1441.             else
  1442.             {
  1443.                 SbWriteByte(DSPStartADCDMA);                  // Low speed mode
  1444.                 SbWriteByte((BufLen-1) % 256);
  1445.                 SbWriteByte((BufLen-1) / 256);
  1446.             }
  1447.  
  1448.             dma_setup(SBdma,DMABufferBase,BufTotal-1,0);
  1449.         }
  1450.  
  1451. #ifdef DEBUG_DMASTAT
  1452.     poke(0xB800,154,11824+BufQueueHead);
  1453.     poke(0xB800,156,11824+BufQueueTail);
  1454.     poke(0xB800,158,11824+DMABufsFull);
  1455. #endif
  1456.  
  1457.         return 3;
  1458.     }
  1459.     else
  1460.         if( BufQueueHead == BufQueueTail )
  1461.             return 2;
  1462.         else
  1463.         {
  1464.             memcpy(ptr,DMABuffers[BufQueueHead],BufLen);
  1465.  
  1466.             disable();
  1467.                 BufQueueHead = (BufQueueHead+1)%BufCount;
  1468.             enable();
  1469.  
  1470.             DMABufsFull--;
  1471.  
  1472. #ifdef DEBUG_DMASTAT
  1473.             poke(0xB800,154,11824+BufQueueHead);
  1474.             poke(0xB800,156,11824+BufQueueTail);
  1475.             poke(0xB800,158,11824+DMABufsFull);
  1476. #endif
  1477.  
  1478.             if( dsp_overrun > 0 )
  1479.             {
  1480.                 dsp_overrun = 0;
  1481.                 return 1;
  1482.             }
  1483.             else
  1484.                 return 0;
  1485.         }
  1486. }
  1487.  
  1488.  
  1489. int sb_get_params(int *port, int *dma, int *irq, int *dma16)
  1490. {
  1491.     char *t, *t1, *blaster;
  1492.  
  1493.     /* Set arguments to reasonable values (Soundblaster defaults) */
  1494.     *port = 0x220;
  1495.     *irq = 5;
  1496.     *dma = 1;
  1497.     *dma16 = 5;
  1498.  
  1499.     /* Attempt to read environment variable */
  1500.     t = getenv("BLASTER");
  1501.  
  1502.     /* Is the environment variable set? */
  1503.     if(t == NULL)
  1504.         return 0;
  1505.  
  1506.     /* Duplicate the string so that we don't trash our environment */
  1507.     blaster = strdup(t);
  1508.  
  1509.     /* Now parse the BLASTER variable */
  1510.     t = strtok(blaster," \t");
  1511.  
  1512.     while(t)
  1513.     {
  1514.         switch(toupper(t[0]))
  1515.         {
  1516.             case 'A':                               /* I/O address */
  1517.                 *port = (int)strtol(t+1,&t1,16);
  1518.             break;
  1519.  
  1520.             case 'I':                               /* Hardware IRQ */
  1521.                 *irq = atoi(t+1);
  1522.             break;
  1523.  
  1524.             case 'D':                               /* DMA channel */
  1525.                 *dma = atoi(t+1);
  1526.             break;
  1527.  
  1528.             case 'H':
  1529.                 *dma16 = atoi(t+1);
  1530.             break;
  1531.         }
  1532.         t = strtok(NULL," \t");
  1533.     }
  1534.  
  1535. #ifdef DEBUG_PROC
  1536.     printf("sb_get_params: A%3X I%i D%i H%i\n",*port,*irq,*dma,*dma16);
  1537. #endif
  1538.  
  1539.     free(blaster);
  1540.     return 1;
  1541. }
  1542.  
  1543. int mix_reset(void)
  1544. {
  1545.     SbWriteMixerReg(0,0);
  1546.  
  1547.     return !!(SbReadMixerReg(4));
  1548. }
  1549.  
  1550. unsigned char mix_read(int device, int channel)
  1551. {
  1552.     int r1;
  1553.     int ll=0,lr=0;
  1554.  
  1555.     if( device > 8 )
  1556.         channel = SBtype >= 4 ? MIXleft : MIXright;
  1557.  
  1558.     if( SBtype <= 3 && SBProMixRegs[device] )
  1559.     {
  1560.         r1 = SbReadMixerReg(SBProMixRegs[device]); // Read register
  1561.  
  1562.         ll = (r1 & 0xF0);                       // Left channel: High nibble
  1563.         lr = (r1 & 0x0F) << 4;           // Right channel: Low nibble
  1564.     }
  1565.  
  1566.     if( SBtype >= 4 && SB16MixRegs[device] )
  1567.     {
  1568.         ll = SbReadMixerReg(SB16MixRegs[device]);        // Given byte: Left
  1569.         lr = SbReadMixerReg(SB16MixRegs[device]+1);     // Byte+1: Right
  1570.     }
  1571.  
  1572.     if( (SBtype <= 3) && (device == MIXmicrophone) )
  1573.         lr <<= 1;
  1574.  
  1575. #ifdef DEBUG_PROC
  1576.     printf("mix_read: %i %i (%i %i)\n",device,channel,ll,lr);
  1577. #endif
  1578.  
  1579.     switch( channel )
  1580.     {
  1581.         case MIXleft:     return ll;
  1582.         case MIXright: return lr;
  1583.         case MIXboth:  return (ll+lr)/2;
  1584.     }
  1585.  
  1586.    return 0;
  1587. }
  1588.  
  1589. void mix_write(int device, int channel, unsigned char level)
  1590. {
  1591.     int r1,r2;
  1592.  
  1593. #ifdef DEBUG_PROC
  1594.     printf("mix_write: device %i channel %i level %i\n",device,channel,(int)level);
  1595. #endif
  1596.  
  1597.     if( device > 8 )
  1598.         channel = SBtype >= 4 ? MIXleft : MIXright;
  1599.  
  1600.     if( (SBtype <= 3) && (device == MIXmicrophone) )
  1601.         level >>= 1;
  1602.  
  1603.     if( SBtype <= 3 && SBProMixRegs[device] )        // Soundblaster Pro shares each register between two channels
  1604.     {
  1605.         r1 = SbReadMixerReg(SBProMixRegs[device]);
  1606.  
  1607.         switch( channel )            // We have to set the correct part of the byte.
  1608.         {
  1609.             case MIXright: r2 = (r1 & 0xF0) + (level>>4); break;
  1610.             case MIXleft:     r2 = (r1 & 0x0F) + (level & 0xF0); break;
  1611.             case MIXboth:  r2 = (level & 0xF0) + (level>>4); break;
  1612.         }
  1613.  
  1614.         SbWriteMixerReg(SBProMixRegs[device],r2);
  1615.     }
  1616.  
  1617.     if( SBtype >= 4 && SB16MixRegs[device] )            // Soundblaster 16 uses register per channel
  1618.         switch( channel )                                        // Makes things a bit easier, no?
  1619.         {
  1620.             case MIXleft:    SbWriteMixerReg(SB16MixRegs[device]  ,level); break;
  1621.             case MIXright:    SbWriteMixerReg(SB16MixRegs[device]+1,level); break;
  1622.             case MIXboth:  SbWriteMixerReg(SB16MixRegs[device]  ,level);
  1623.                                 SbWriteMixerReg(SB16MixRegs[device]+1,level); break;
  1624.         }
  1625. }
  1626.  
  1627.  
  1628. void mix_set_sb16_output(int value)
  1629. {
  1630. #ifdef DEBUG_PROC
  1631.     printf("mix_set_sb16_output: %i\n",value);
  1632. #endif
  1633.  
  1634.     SbWriteMixerReg(0x3C,value);           // Send output value raw :)
  1635. }
  1636.  
  1637. void mix_set_sb16_input(int channel, int value)
  1638. {
  1639. #ifdef DEBUG_PROC
  1640.     printf("mix_set_sb16_value: channel %i value %i\n",channel,value);
  1641. #endif
  1642.  
  1643.     switch( channel )
  1644.     {
  1645.         case MIXboth:  SbWriteMixerReg(0x3E,value);
  1646.         case MIXleft:  SbWriteMixerReg(0x3D,value); break;
  1647.         case MIXright: SbWriteMixerReg(0x3E,value); break;
  1648.     }
  1649. }
  1650.  
  1651. void mix_set_input(int value)
  1652. {
  1653.     int i;
  1654.  
  1655. #ifdef DEBUG_PROC
  1656.     printf("mix_set_input: %x",value);
  1657. #endif
  1658.  
  1659.     SbReadMixerReg(0x0C);            // Read input control byte
  1660.  
  1661. /*  bit:  7 6 5 4 3 2 1 0           F=frequency (0=low, 1=high)
  1662.              x x T x F S S x           SS=source (00=MIC, 01=CD, 11=LINE)
  1663.                                                 T=input filter switch (ANFI) */
  1664.  
  1665. //    i &= 0xF9;
  1666.     i |= 0x20;
  1667.  
  1668.     switch( value )
  1669.     {
  1670.         case 0x18: i |= 6; break;
  1671.         case 0x06: i |= 2; break;
  1672.         case 0x01: break;
  1673.     }
  1674.  
  1675.  
  1676.     SbWriteMixerReg(0x0C,i);              // Write input control byte
  1677. }
  1678.